﻿using HandyControl.Controls;
using Ping9719.WpfEx.Mvvm;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BaseUi.ViewModel
{
    //https://dandelioncloud.cn/article/details/1472765022102446082
    public class RoleEditTreeViewModel : BindableBase, ITreeNode<RoleEditTreeViewModel>
    {
        private bool IsSelect_;
        /// <summary>
        /// 是否选择
        /// </summary>
        public bool IsSelect { get => IsSelect_; set { SetProperty(ref IsSelect_, value); Linkage(value); } }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 主键Id
        /// </summary>
        public object Id { get; set; }
        /// <summary>
        /// 父Id
        /// </summary>
        public object Pid { get; set; }

        /// <summary>
        /// 父级
        /// </summary>
        public RoleEditTreeViewModel Parent { get; set; }

        /// <summary>
        /// 子级
        /// </summary>
        public List<RoleEditTreeViewModel> Children { get; set; }

        /// <summary>
        /// 联动
        /// </summary>
        public void Linkage(bool newbool)
        {
            //父级增加联动
            if (newbool && Parent != null)
                Parent.IsSelect = true;

            //子级联动
            if (!newbool && Children != null)
                foreach (var item in Children)
                    item.IsSelect = false;
        }

        /// <summary>
        /// 得到数据
        /// </summary>
        /// <param name="select">选中的值</param>
        /// <returns></returns>
        public static List<RoleEditTreeViewModel> GetTreeViewModel(List<int> select)
        {
            //值,名称，父级，子级
            List<Tuple<int, string, int?, List<int>>> quan = new List<Tuple<int, string, int?, List<int>>>();
            List<RoleEditTreeViewModel> vmodel = new List<RoleEditTreeViewModel>();

            //1：解析枚举
            {
                Type type = typeof(AuthEnum);
                var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public) ?? new FieldInfo[] { };
                foreach (var field in fields)
                {
                    var attr = field.GetCustomAttribute<EnumTreeAttribute>(false);
                    var attr1 = field.GetCustomAttribute<DescriptionAttribute>(false);

                    var v0 = Convert.ToInt32(field.GetRawConstantValue());
                    var v1 = attr1 == null ? field.Name : attr1.Description;
                    var v2 = (int?)attr?.Parent;
                    var v3 = attr?.Childs?.Select(o => (int)o)?.ToList();
                    quan.Add(new Tuple<int, string, int?, List<int>>(v0, v1, v2, (v3 ?? new List<int>())));
                }
            }

            //2：翻译数据
            {
                vmodel.AddRange(quan.Select(o => new RoleEditTreeViewModel()
                {
                    Id = o.Item1,
                    Name = o.Item2,
                    Pid = 0,
                    IsSelect = select?.Contains(o.Item1) ?? false,
                }));

                //父子
                foreach (var item in vmodel)
                {
                    var f = quan.FirstOrDefault(o => o.Item1 == (int)item.Id)?.Item3;
                    if (f.HasValue)
                    {
                        item.Parent = vmodel.FirstOrDefault(o => (int)o.Id == f.Value);
                        item.Pid = item.Parent.Id;
                    }

                    var ff = quan.FirstOrDefault(o => o.Item1 == (int)item.Id)?.Item4;
                    if (ff != null && ff.Any())
                    {
                        foreach (var item2 in ff)
                        {
                            vmodel.FirstOrDefault(o => (int)o.Id == item2).Parent = item;
                            vmodel.FirstOrDefault(o => (int)o.Id == item2).Pid = item.Id;
                        }
                    }
                }
            }

            //3：数据转为树对象
            vmodel = vmodel.ToTree();
            return vmodel;
        }
    }
}
